--- sys/dev/xen/blkfront/blkfront.c.orig
+++ sys/dev/xen/blkfront/blkfront.c
@@ -1529,6 +1529,11 @@
 {
 	struct xbd_softc *sc = device_get_softc(dev);
 
+	if (xen_suspend_cancelled) {
+		sc->xbd_state = XBD_STATE_CONNECTED;
+		return (0);
+	}
+
 	DPRINTK("xbd_resume: %s\n", xenbus_get_node(dev));
 
 	xbd_free(sc);
--- sys/dev/xen/control/control.c.orig
+++ sys/dev/xen/control/control.c
@@ -148,6 +148,7 @@
 
 #include <xen/xenbus/xenbusvar.h>
 
+bool xen_suspend_cancelled;
 /*--------------------------- Forward Declarations --------------------------*/
 /** Function signature for shutdown event handlers. */
 typedef	void (xctrl_shutdown_handler_t)(void);
@@ -196,10 +197,11 @@
 #ifdef SMP
 	cpuset_t cpu_suspend_map;
 #endif
-	int suspend_cancelled;
 
 	EVENTHANDLER_INVOKE(power_suspend_early);
+	xs_lock();
 	stop_all_proc();
+	xs_unlock();
 	EVENTHANDLER_INVOKE(power_suspend);
 
 #ifdef EARLY_AP_STARTUP
@@ -267,16 +269,20 @@
 	intr_suspend();
 	xen_hvm_suspend();
 
-	suspend_cancelled = HYPERVISOR_suspend(0);
+	xen_suspend_cancelled = !!HYPERVISOR_suspend(0);
 
-	xen_hvm_resume(suspend_cancelled != 0);
-	intr_resume(suspend_cancelled != 0);
+	if (!xen_suspend_cancelled) {
+		xen_hvm_resume(false);
+	}
+	intr_resume(xen_suspend_cancelled != 0);
 	enable_intr();
 
 	/*
 	 * Reset grant table info.
 	 */
-	gnttab_resume(NULL);
+	if (!xen_suspend_cancelled) {
+		gnttab_resume(NULL);
+	}
 
 #ifdef SMP
 	if (!CPU_EMPTY(&cpu_suspend_map)) {
--- sys/dev/xen/netfront/netfront.c.orig
+++ sys/dev/xen/netfront/netfront.c
@@ -458,7 +458,21 @@
 netfront_resume(device_t dev)
 {
 	struct netfront_info *info = device_get_softc(dev);
+	u_int i;
 
+	if (xen_suspend_cancelled) {
+		for (i = 0; i < info->num_queues; i++) {
+			XN_RX_LOCK(&info->rxq[i]);
+			XN_TX_LOCK(&info->txq[i]);
+		}
+		netfront_carrier_on(info);
+		for (i = 0; i < info->num_queues; i++) {
+			XN_RX_UNLOCK(&info->rxq[i]);
+			XN_TX_UNLOCK(&info->txq[i]);
+		}
+		return (0);
+	}
+
 	netif_disconnect_backend(info);
 	return (0);
 }
--- sys/dev/xen/timer/timer.c.orig
+++ sys/dev/xen/timer/timer.c
@@ -417,8 +417,20 @@
 	/* Register the timecounter. */
 	sc->tc.tc_name = "XENTIMER";
 	sc->tc.tc_quality = XENTIMER_QUALITY;
-	sc->tc.tc_flags = TC_FLAGS_SUSPEND_SAFE;
 	/*
+	 * FIXME: due to the lack of ordering during resume, FreeBSD cannot
+	 * guarantee that the Xen PV timer is resumed before any other device
+	 * attempts to make use of it, so mark it as not safe for suspension
+	 * (ie: remove the TC_FLAGS_SUSPEND_SAFE flag).
+	 *
+	 * NB: This was not a problem in previous FreeBSD versions because the
+	 * timer was directly attached to the nexus, but it is an issue now
+	 * that the timer is attached to the xenpv bus, and thus resumed
+	 * later.
+	 *
+	 * sc->tc.tc_flags = TC_FLAGS_SUSPEND_SAFE;
+	 */
+    	/*
 	 * The underlying resolution is in nanoseconds, since the timer info
 	 * scales TSC frequencies using a fraction that represents time in
 	 * terms of nanoseconds.
--- sys/dev/xen/xenstore/xenstore.c.orig
+++ sys/dev/xen/xenstore/xenstore.c
@@ -1699,3 +1699,20 @@
 		sx_xunlock(&xs.xenwatch_mutex);
 	}
 }
+
+void
+xs_lock(void)
+{
+
+	sx_xlock(&xs.request_mutex);
+	return;
+}
+
+void
+xs_unlock(void)
+{
+
+	sx_xunlock(&xs.request_mutex);
+	return;
+}
+
--- sys/xen/xen-os.h.orig
+++ sys/xen/xen-os.h
@@ -56,6 +56,8 @@
 extern int xen_disable_pv_disks;
 extern int xen_disable_pv_nics;
 
+extern bool xen_suspend_cancelled;
+
 enum xen_domain_type {
 	XEN_NATIVE,             /* running on bare hardware    */
 	XEN_PV_DOMAIN,          /* running in a PV domain      */
--- sys/xen/xenbus/xenbusb.c.orig
+++ sys/xen/xenbus/xenbusb.c
@@ -791,6 +791,11 @@
 			if (device_get_state(kids[i]) == DS_NOTPRESENT)
 				continue;
 
+			if (xen_suspend_cancelled) {
+				DEVICE_RESUME(kids[i]);
+				continue;
+			}
+
 			ivars = device_get_ivars(kids[i]);
 
 			xs_unregister_watch(&ivars->xd_otherend_watch);
--- sys/xen/xenstore/xenstorevar.h.orig
+++ sys/xen/xenstore/xenstorevar.h
@@ -338,4 +338,15 @@
  */
 struct sbuf *xs_join(const char *, const char *);
 
+/**
+ * Lock the xenstore request mutex.
+ */
+void xs_lock(void);
+
+/**
+ * Unlock the xenstore request mutex.
+ */
+void xs_unlock(void);
+
 #endif /* _XEN_XENSTORE_XENSTOREVAR_H */
+
